--[[
--
--  Parsermodule for CRT
--
--]]

local realLocale = GetLocale()

local function GetLocale()
 if realLocale ~= "deDE" and realLocale ~= "enUS" then 
  return "enUS";
 else
  return realLocale;
 end
end

local function RGBPercToHex(r, g, b)
	r = r <= 1 and r >= 0 and r or 0
	g = g <= 1 and g >= 0 and g or 0
	b = b <= 1 and b >= 0 and b or 0
	return string.format("%02x%02x%02x", r*255, g*255, b*255)
end

local function money()
local start, ende, gold, silver, copper;
 if strlen(GetMoney()) > 4 then
  start, ende, gold, silver, copper = string.find(GetMoney(),"(%d+)(%d.)(%d.)")
 elseif strlen(GetMoney()) > 2 then
  start, ende, silver, copper = string.find(GetMoney(),"(%d.)(%d.)")
  gold = 0
 else
  start, ende, copper = string.find(GetMoney(),"(%d.)")
  gold = 0
  silver = 0
 end
 return tonumber(gold,10), tonumber(silver,10), tonumber(copper,10)
end

local function skillinfo(name)
	if skillname then
		for i=1, GetNumSkillLines() do
			local skillName, _, _, rank, _, _, maxRank = GetSkillLineInfo(i)
			if skillName == name then
				return rank, maxRank
			end
		end
	end
	return 0, 0
end

local function itemcount(item)
	return item and GetItemCount(item) or "0"
end

local Scaning = {
 "CharacterHeadSlot",
 "CharacterNeckSlot",
 "CharacterShoulderSlot",
 "CharacterBackSlot",
 "CharacterChestSlot",
 "CharacterShirtSlot",
 "CharacterTabardSlot",
 "CharacterWristSlot",
 "CharacterHandsSlot",
 "CharacterWaistSlot",
 "CharacterLegsSlot",
 "CharacterFeetSlot",
 "CharacterMainHandSlot",
 "CharacterSecondaryHandSlot",
 "CharacterRangedSlot",
};

local static_colors = {
 ["RED"] = "FFFF0000",
 ["BLUE"] = "FF0000FF",
 ["LIME"] = "FF00FF00",
 ["YELLOW"] = "FFFFFF00",
 ["VIOLET"] = "FFFF00FF",
 ["ORANGE"] = "FFFF6600",
 ["BLACK"] = "FF000000",
 ["WHITE"] = "FFFFFFFF",
 ["GOLD"] = "FFFFB311",
 ["SILVER"] = "FFE1D3CB",
 ["COPPER"] = "FFE16B47",
 ["REPUTATION"] = function()
    local name, standing, min, max, value = GetWatchedFactionInfo()
	if standing == 1 then -- Hated
	  return "FFB82E21"
elseif standing == 2 then -- Hostile
      return "FFC9662B"
elseif standing == 3 then -- Unfriendly
      return "FFD59B31"
elseif standing == 4 then -- Neutral
      return "FFD2B130"
elseif standing == 5 then -- Friendly
      return "FFA4A201"
elseif standing == 6 then -- Honored 
      return "FF74A001"
elseif standing == 7 then -- Revered
      return "FF258001"
elseif standing == 8 then -- Exalted
      return "FF10A087"
else
      return "FF666666" -- unkown
    end	
 end,
}

paramFuncs = {	-- update functions for keys with parameters
											-- use matches as keys
	["%[classcolor(.-)%]"] = function(class)
	    class = string.upper(strsub(class, 2))
		for english,colors in pairs (RAID_CLASS_COLORS) do
		 if class == english then
		  local cR, cG, cB = RAID_CLASS_COLORS[class].r, RAID_CLASS_COLORS[class].g, RAID_CLASS_COLORS[class].b
 	      return "|cFF"..RGBPercToHex(cR, cG, cB)
		 end
		end
        local playerClass = select(2, UnitClass("player"))
        local cR, cG, cB = RAID_CLASS_COLORS[playerClass].r, RAID_CLASS_COLORS[playerClass].g, RAID_CLASS_COLORS[playerClass].b
		return "|cFF"..RGBPercToHex(cR, cG, cB)
	end,
	["%[copper%]"] = function()
	    return select(3,money())
	end,
	["%[gold%]"] = function()
	    return select(1,money())
	end,
	["%[silver%]"] = function()
	    return select(2,money())
	end,
	["%[itemcount(.-)%]"] = function(item)
	    item = strsub(item, 2)
		return itemcount(item)
	end, 
 	["%[skillmaxlevel(.-)%]"] = function(name)
 		local _, max = skillinfo(name)
 		return max
 	end,
 	["%[skilllevel(.-)%]"] = function(name)
 		return skillinfo(name)
 	end, 
	["%[durability(.-)%]"] = function(precision)
		if precision ~= nil then
			precision = strsub(precision, 2)
		end
		if not string.find(precision,"(%d)") then precision = "0" end
		if not getglobal("ScanTooltip") then
			ScanTooltip = CreateFrame("GameTooltip","ScanTooltip",UIParent,"GameTooltipTemplate")
		end
		local start, ende, current, maximal
		local totalcurrent = 0
		local totalmaximal = 0
		for key, item in pairs (Scaning) do
			ScanTooltip:SetOwner(UIParent, "ANCHOR_NONE")
			ScanTooltip:SetInventoryItem("player",getglobal(item):GetID())
			for i=1,ScanTooltip:NumLines() do 
				if string.find(getglobal("ScanTooltipTextLeft"..i):GetText(),"(%d+) / (%d+)") then 
					start, ende, current, maximal = string.find(getglobal("ScanTooltipTextLeft"..i):GetText(),"(%d+) / (%d+)") 
					 totalcurrent = totalcurrent + current
					 totalmaximal = totalmaximal + maximal
				end 
			end 
			ScanTooltip:Hide()
		end
		return string.format("%."..precision.."f", (totalcurrent / totalmaximal) * 100)
	end,
	["%[color(.-)%]"]= function(clr)
	    clr = strsub(clr, 2)
		if string.upper(clr) == "REPUTATION" then
		 return "|c".. static_colors["REPUTATION"]()
		end
		for colorname, color in pairs(static_colors) do
		 if string.upper(colorname) == string.upper(clr) then
		  return "|c".. color
		end
		end
		return "|c".. clr
	end,
	["%[downlink(.-)%]"] =function(precision)
	    if precision ~= nil then
     	precision = strsub(precision, 2)
		if not string.find(precision,"(%d)") then precision = "0" end
		return  string.format('%.'..precision..'f', GetNetStats())
		else
		return  string.format('%.0f', GetNetStats())
		end
	end,
	["%[uplink(.-)%]"] = function(precsision) 
		local _, ul = GetNetStats()
	    if precision ~= nil then
     	precision = strsub(precision, 2)
		if not string.find(precision,"(%d)") then precision = "0" end
		return  string.format('%.'..precision..'f', GetNetStats())
		else
		return  string.format('%.0f', ul)
		end
		end,
	["%[ping%]"] = function()
		local _, _, p = GetNetStats()
		return  p
	end,
	["%[fps(.-)%]"] = function(precision)
        precision = strsub(precision, 2)
        if not string.find(precision,"(%d)") then precision = "0" end		
		return string.format('%.'..precision..'f',GetFramerate())
	end,
	["%[seconds%]"] = function() 
		return date("%S")
	end,
	["%[minutes%]"] = function()
		return date("%M")
	end,
	["%[hours%]"] = function()
		return date("%H")
	end,
	["%[day%]"] = function()
		return date("%d")
	end,
	["%[month%]"] =function() 
		return date("%m")
	end,
	["%[year%]"] = function()
		return date("%y")
	end,
	["%[tracking%]"] = function() 
		for index, value in pairs(trackings) do
			if (GetTrackingTexture() == trackings[index].file) then
				local _, class = UnitClass("player")
				if class == "DRUID" and trackings[index].file == "Interface\\Icons\\Ability_Tracking" then
					return trackings_fix[GetLocale()];
				end
				return trackings[index][GetLocale()];
			end
		end 
		return trackings_none[GetLocale()]
	end,
	["%[mail%]"] = function() 
		if HasNewMail() ~= nil then 
			return mail_status[1][GetLocale()]
		else
			return mail_status[2][GetLocale()]
		end
	end,
	["%[location(.-)%]"] = function(where)
        where = strsub(where,2)
        if string.lower(tostring(where)) == "map" then return GetMinimapZoneText()
    elseif string.lower(tostring(where)) == "zone" then return GetSubZoneText()
    elseif string.lower(tostring(where)) == "dynamic" then return GetRealZoneText()
	else
		return GetZoneText()
	end
	end,
	["%[friends(.-)%]"] = function(func)
		func = strsub(func,2)
		if string.lower(func) == "count" then return GetNumFriends()
	elseif string.lower(func) == "online" then 
	    local onlinecount = 0
		for i=0, GetNumFriends() do
		if select(5,GetFriendInfo(i)) == 1 then onlinecount = onlinecount + 1 end
		end
		return onlinecount
	else return "0"
	end
	end,
	["%[guild(.-)%]"] = function(func)
		func = strsub(func,2)
		if GetGuildInfo("player") then
		if string.lower(func) == "name" then return select(1, GetGuildInfo("player")) 
	elseif string.lower(func) == "online" then return GetNumGuildMembers()
	elseif string.lower(func) == "count" then return GetNumGuildMembers(true)
	elseif string.lower(func) == "offline" then return GetNumGuildMembers(true) - GetNumGuildMembers()
	elseif string.lower(func) == "rank" then return select(2, GetGuildInfo("player"))
	else return ""
	end
	   else
	    return ""
	   end
	end,
	["%[pvp%]"] = function()
	   if UnitIsPVP("player") then return "pvp"
   elseif UnitIsPVPFreeForAll("player") then return "ffa"
   else return "pve"
      end
	end,
	["%[cooldown(.-)%]"] = function(SkillOrItem)
	   SkillOrItem = strsub(SkillOrItem,2)	   
	   local start,duration, enabled = GetSpellCooldown(SkillOrItem)
       if start ~= nil then
          if enabled == 0 then
             return "0"
      elseif start > 0 and duration > 0 then
             return string.format("%.1f",start + duration - GetTime())
      else
             return ready[GetLocale()]
          end
       end
       local start,duration,enabled = GetItemCooldown(SkillOrItem)
       if start ~= nil then
          if enabled == 0 then
             return "0"
      elseif start > 0 and duration > 0 then
             return string.format("%.1f",start + duration - GetTime())
      else
             return ready[GetLocale()]
          end
       end
       return ""
       end,
    ["%[stat(.-)%]"] = function(stat)
	  local err,itemBonusLib = pcall(AceLibrary,"ItemBonusLib-1.0")
	  if err == true then
	   stat = strsub(stat,2)
	   if tostring(stat) ~= nil then 
	    stat = string.upper(stat)
	    if itemBonusLib:IsValidName(stat) then
	    return itemBonusLib:GetBonus(stat)

	  else	
	    return "Syntax Error" 
	  end
	  end
	else
       DEFAULT_CHAT_FRAME:AddMessage("To use this tag you need to install '|cffff8900ItemBonusLib|r'")
	end
	end,
	["%[ramusage(.-)%]"] = function(precision)
	    precision = strsub(precision,2)
		if not string.find(precision,"(%d)") then precision = "0" end
		return string.format('%.'..precision..'f',collectgarbage("count")/1024)
	end,
	["%[reputation(.-)%]"] = function(func)
	    func = strsub(func,2)
		local name, standing, min, max, value = GetWatchedFactionInfo()
		if string.lower(tostring(func)) == "min" then return min - min
	elseif string.lower(tostring(func)) == "max" then return max - min
	elseif string.lower(tostring(func)) == "name" then return name
	elseif string.lower(tostring(func)) == "current" then return value - min
	elseif string.lower(tostring(func)) == "standing" then return getglobal("FACTION_STANDING_LABEL"..standing)
	else
	    return name
	end
	end,
	["%[ammocount%]"] = function()
		local ammoSlot = GetInventorySlotInfo("AmmoSlot")
		local ammoCount = GetInventoryItemCount("player", ammoSlot);
		if ((ammoCount == 1) and (not GetInventoryItemTexture("player", ammoSlot))) then
			return 0
		else
			return ammoCount
		end
	end,
	["%[bag(.-)%]"] = function(func)
	    local free= 0
		local used = 0 
		local maximum = 0
		  for bag=0,4 do
		  if GetBagName(bag) and select(8, GetItemInfo(GetBagName(bag))) ~= "INVTYPE_QUIVER" then
           for slot=1,GetContainerNumSlots(bag) do
            if (GetContainerItemLink(bag,slot)) then
			 used = used + 1
			 maximum = maximum + 1
            else
			 free = free + 1
			 maximum = maximum + 1
			end
           end
          end
		  end
          func = strsub(func, 2)
          if string.lower(func) == "used" then return used
      elseif string.lower(func) == "free" then return free
      elseif string.lower(func) == "maximum" then return maximum
      end	  
	end,
	["%[currentxp%]"] = function()
		return UnitXP('player')


	end,
	["%[percentxp(.-)%]"] = function(precision)
	    precision = strsub(precision, 2)
		if not string.find(precision,"(%d)") then precision = "0" end
		return string.format('%2.'..precision..'f',UnitXP('player') / UnitXPMax('player')*100)
	end,
	["%[maxxp%]"] = function()
		return UnitXPMax("player")
	end,
	["%[nextlvl%]"] = function()
		return UnitLevel("player") + 1
	end,
	["%[lvl%]"] = function()
		return UnitLevel("player")
	end,	
	["%[calc(.-):(%d)%]"] = function(eval,precision)
		eval = strsub(eval, 2)
		--eval = string.gsub(eval,ready[GetLocale()],"0")
		local err, value = pcall(loadstring("return "..eval))
		if err == true then 
		 if not string.find(precision,"(%d)") then precision = 1 end
		 if tonumber(value) then
		 return string.format("%."..precision.."f",value)
		 else
		 return value
		 end
		else
		 if string.find(eval,ready[GetLocale()]) then
		 return ready[GetLocale()]
		 else
		 return "0"
		 end
		end
	end,
}	

info_ = paramFuncs

local updateInterval = 1.0

function crt_refreshTokens(self, elapsed)
	self.TimeSinceLastUpdate = self.TimeSinceLastUpdate + elapsed
	if self.TimeSinceLastUpdate > updateInterval then
		for key, func in pairs(updateFuncs) do
			values[key] = func()
		end
		
		self.TimeSinceLastUpdate = 0
	end
end

function crt_parser(text)
	for key, func in pairs(paramFuncs) do
		text = text:gsub(key, func)
	end
	
	return text
end 